home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 26 / AACD 26.iso / AACD / Programming / ace_gpl_release / src / lib / asm / string.s < prev    next >
Encoding:
Text File  |  1998-10-04  |  18.2 KB  |  864 lines

  1. ;
  2. ; string.s -- an ACE linked library module: string functions.
  3. ; Copyright (C) 1998 David Benn
  4. ; This program is free software; you can redistribute it and/or
  5. ; modify it under the terms of the GNU General Public License
  6. ; as published by the Free Software Foundation; either version 2
  7. ; of the License, or (at your option) any later version.
  8. ;
  9. ; This program is distributed in the hope that it will be useful,
  10. ; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. ; GNU General Public License for more details.
  13. ;
  14. ; You should have received a copy of the GNU General Public License
  15. ; along with this program; if not, write to the Free Software
  16. ; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  17. ;
  18. ; Author: David J Benn
  19. ;   Date: 3rd-30th November, 1st-13th December 1991,
  20. ;      20th, 23rd,25th-27th January 1992, 
  21. ;         2nd,4th,6th,12th-19th,21st-24th,29th February 1992,
  22. ;      1st,14th March 1992,
  23. ;      4th,7th,21st,22nd,26th April 1992,
  24. ;      2nd,3rd,5th,7th,8th,10th-17th May 1992,
  25. ;      6th,8th,11th,12th,28th,30th June 1992,
  26. ;      1st-3rd,13th,14th,18th-20th,22nd July 1992,
  27. ;      9th August 1992,
  28. ;      5th,13th,29th,30th December 1992,
  29. ;      6th,12th January 1993,
  30. ;      7th,14th,16th,18th February 1993,
  31. ;      1st,14th March 1993,
  32. ;      9th,25th,30th May 1993,
  33. ;      6th,29th June 1993,
  34. ;      9th,11th October 1993,
  35. ;      19th March 1994,
  36. ;      12th,25th July 1994
  37. ;
  38. ; registers d0-d6 and a0-a3 are modified by some of the following. BEWARE!
  39. ;
  40. ; a4,a5 are used by link/unlk.
  41. ; a6 is library base holder.
  42. ; a7 is stack pointer. 
  43. ; d7 is used for array index calculations.
  44. ;
  45.  
  46. ; misc. defines
  47. MAXSTRINGSIZE     equ 1024
  48. VANILLAKEY        equ $00200000
  49. UserPort         equ 86
  50.  
  51. Class        equ 0        ; member in IntuiInfo structure
  52. Code        equ 4        ; member in IntuiInfo structure
  53.                 ; (see intuievent.h)
  54. pr_CLI        equ 172
  55. cli_CommandName    equ 16
  56.  
  57.        ; string functions
  58.     xdef    _htol
  59.        xdef      _leftstr
  60.        xdef      _rightstr
  61.        xdef      _midstr
  62.     xdef    _ucase
  63.     xdef    _inputstring
  64.     xdef    _hexstrlong
  65.     xdef    _hexstrshort
  66.     xdef    _octstr
  67.     xdef    _binstr
  68.     xdef    _strlong
  69.     xdef    _strshort
  70.     xdef    _inkey
  71.     xdef    _spacestring
  72.     xdef    _spc
  73.     xdef    _stringstr
  74.     xdef    _instr
  75.  
  76.        ; external references 
  77.     xref    _strlen
  78.     xref    _strcpy
  79.     xref    _streq
  80.  
  81.     xref    _shortfmt
  82.     xref    _longfmt
  83.     xref    _shorthexfmt
  84.     xref    _longhexfmt
  85.     xref    _zerostr
  86.     xref    _colonstr
  87.  
  88.     xref    _tmpstring
  89.     xref    _deststraddr
  90.     xref    _count
  91.     xref    _ucasestring
  92.     xref    _spacestraddress
  93.     xref    _stringstraddress
  94.     xref    _octdigit
  95.     xref    _bindigit
  96.     xref    _inkeybuf
  97.     xref    _rawinpbuf
  98.     xref    _rawinpaddr
  99.     xref    _instrposn
  100.     xref    _search_offset
  101.     xref    _targetch
  102.     xref    _x_string
  103.     xref    _y_string
  104.     xref    _x_strlen
  105.     xref    _y_strlen
  106.  
  107.        xref      _putchar
  108.     xref    _sprintf
  109.     xref    _strval
  110.       xref      _LVOSPFlt
  111.     xref    _LVOSPAdd
  112.        xref      _LVOSPDiv
  113.        xref      _LVOSPTst
  114.     xref    _LVOSPNeg
  115.        xref      _LVOWrite
  116.     xref    _LVORead
  117.     xref    _LVOWaitForChar
  118.     xref    _LVOExamine
  119.     xref    _LVOUnLock
  120.       xref      _DOSBase    
  121.        xref      _MathBase
  122.        xref      _stdout
  123.     xref    _stdin
  124.     xref    _turncursoron
  125.     xref    _turncursoroff
  126.         xref     _AbsExecBase
  127.     xref    _LVOFindTask
  128.     xref    _Wdw
  129.     xref    _Wdw_id
  130.     xref    _IntuiMode
  131.     xref    _GetIntuiEvent
  132.     xref    _ClearIntuiEvent
  133.  
  134.     SECTION string_code,CODE
  135.  
  136. ;*** STRING FUNCTIONS ***
  137.  
  138. ;
  139. ; _htol - returns a LONG value in d0 from a HEX string pointed to by a1.
  140. ; _htol assumes that all digits are legal (1..9, a..f) and lowercase. 
  141. ;
  142. _htol:
  143.     moveq    #0,d0
  144. _htoloop:
  145.     cmpi.b    #0,(a1)
  146.     beq.s    _quithtol        ; EOS?
  147.  
  148.     cmpi.b    #57,(a1)        
  149.     ble.s    _decdigit        ; <= 9 ?
  150.  
  151.     ; <= F -> hex digit
  152.     move.b    (a1)+,d1        ; hex digit
  153.     ext.w    d1
  154.     ext.l    d1
  155.     sub.l    #87,d1
  156.     lsl.l    #4,d0            
  157.     add.l    d1,d0
  158.     
  159.     bra.s    _htoloop
  160.     
  161. _decdigit:
  162.     move.b    (a1)+,d1        ; decimal digit
  163.     ext.w    d1
  164.     ext.l    d1
  165.     sub.l    #48,d1
  166.     lsl.l    #4,d0            
  167.     add.l    d1,d0
  168.     
  169.     bra.s    _htoloop
  170. _quithtol:    
  171.     rts
  172.  
  173. ;
  174. ; LEFT$ function. expects string address in a0, sub-string address in a1
  175. ; and index in d0 (SHORT).
  176. ; returns address of sub-string in a0.
  177. ;
  178. _leftstr:
  179.     move.l    a1,a3        ; save address of target sub-string
  180. _leftstrloop:
  181.     cmpi.w    #0,d0        ; transfered n bytes?
  182.     ble.s    _leftstrquit    
  183.     cmpi.b    #0,(a0)        ; EOS?
  184.     beq.s    _leftstrquit
  185.     move.b    (a0)+,(a1)+    ; copy a byte
  186.     subq    #1,d0
  187.     bra.s    _leftstrloop
  188. _leftstrquit:
  189.     move.b    #0,(a1)
  190.     move.l    a3,a0        ; return address of sub-string
  191.     rts
  192.  
  193. ;
  194. ; RIGHT$ function. expects string address in a0, sub-string address in a1 
  195. ; and index in d0 (SHORT).
  196. ; returns address of sub-string in a0.
  197. ;    
  198. _rightstr:
  199.     move.l    a1,a3            ; get address of target sub-string
  200.     move.w    d0,d1        ; save length of sub-string
  201.         cmpi.w    #0,d0
  202.     ble.s    _rightstrquit    ; return NULL string if requested length <= 0
  203.     move.l    a0,a2
  204.     jsr    _strlen        ; d0 = length of string pointed to by a2
  205.     ext.l    d1        
  206.     sub.l    d1,d0        ; starting position = strlen-index
  207.     cmpi.l    #0,d0        
  208.     bgt.s    _rightstrpoint  ; index < strlen(string) -> okay
  209.     moveq    #0,d0        ; index >= strlen(string) so return whole string
  210. _rightstrpoint:
  211.     add.l    d0,a0        ; point to it
  212. _rightstrloop:
  213.     cmpi.b    #0,(a0)        ; EOS?
  214.     beq.s    _rightstrquit
  215.     move.b    (a0)+,(a1)+    ; copy a byte
  216.     subq    #1,d0
  217.     bra.s    _rightstrloop
  218. _rightstrquit:
  219.     move.b    #0,(a1)
  220.     move.l    a3,a0        ; address of sub-string
  221.     rts
  222.  
  223. ;
  224. ; MID$ function. Expects string address in a0, sub-string address in a1,
  225. ; start posn in d0 and length of sub-string in d1 (both SHORT).
  226. ; returns address of sub-string in a0.
  227. ;
  228. ; MID$(X$,n[,m]) -> a0=X$,d0=n,d1=m
  229. ;    
  230. _midstr:
  231.     move.l    a1,a3        ; save address of target sub-string
  232.     move.w    d0,d2        ; save start position (n)
  233.     move.l    a0,a2
  234.     jsr    _strlen        ; d0 = length of string pointed to by a2
  235.     cmpi.w    #-1,d1        
  236.     bne.s    _midstr1
  237.     move.w    d0,d1        ; if m is -1 -> take FULL length of string 
  238. _midstr1:
  239.     ext.l    d2
  240.     cmp.l    d0,d2        
  241.     bgt.s    _midstrquit    ; n > strlen(string)? -> quit
  242.     cmpi.w    #0,d1
  243.     bge.s    _midstrpoint    ; negative? -> make zero
  244.     moveq    #0,d1
  245. _midstrpoint:
  246.     add.l    d2,a0        ; start at nth character
  247.     subq    #1,a0        
  248. _midstrloop:
  249.     cmpi.w    #0,d1        
  250.     beq.s    _midstrquit    ; m characters copied?
  251.     cmpi.b    #0,(a0)        
  252.     beq.s    _midstrquit    ; EOS?
  253.     move.b    (a0)+,(a1)+    ; copy a byte
  254.     subq    #1,d1
  255.     bra.s    _midstrloop
  256. _midstrquit:
  257.     move.b    #0,(a1)
  258.     move.l    a3,a0        ; return sub-string address
  259.     rts
  260.     
  261. ;
  262. ; UCASE$ - Convert lower case characters in string (a1) to upper case. 
  263. ;        - Destination string in a0.
  264. ;
  265. _ucase:
  266.     ; store destination address
  267.      move.l    a0,_ucasestring
  268.  
  269.     ; make a copy
  270.     jsr    _strcpy
  271.  
  272.     ; main loop
  273.     movea.l    _ucasestring,a1
  274. _ucaseloop:
  275.     cmpi.b    #0,(a1)    
  276.     beq.s    _ucaseexit    ; EOS?
  277.     cmpi.b  #97,(a1)    
  278.     blt.s    _nextchar    ; (a0) < 'a'?
  279.     cmpi.b    #122,(a1)    
  280.     bgt.s    _nextchar    ; (a0) > 'z'?
  281.     sub.b    #32,(a1)    ; 'a'..'z' -> make 'A'..'Z'
  282. _nextchar:
  283.     addq    #1,a1
  284.     bra.s    _ucaseloop
  285. _ucaseexit:
  286.     movea.l    _ucasestring,a0
  287.     rts
  288.  
  289. ;
  290. ; get a string from _stdin and return it's address in a0.
  291. ; expects target string address in a1. 
  292. ;
  293. _inputstring:
  294.         move.l  a1,a3        ; save input string address
  295.  
  296.     jsr    _turncursoron
  297.  
  298.     ; get the string
  299.     cmpi.w    #0,_Wdw_id
  300.     beq.s    _inputconstring    ; if Wdw-id = 0 then window is CON: 
  301.     jsr    _inputrawstring    ; if Wdw-id <> 0 then window is RAW:
  302.     bra.s    _exitinputstring
  303.  
  304. _inputconstring:
  305.     move.l    _DOSBase,a6    
  306.     move.l    _stdin,d1
  307.     move.l    a3,d2        ; get start address of input string    
  308.     move.l    #MAXSTRINGSIZE-1,d3; allow the max string size. d0=actual.
  309.     jsr    _LVORead(a6)
  310.     move.l    a3,a0
  311.     subq    #1,d0
  312.     clr.b    0(a0,d0)    ; append EOS character    
  313.  
  314. _exitinputstring:
  315.     jsr    _turncursoroff
  316.  
  317.     move.l    a3,a0        ; restore start address of input string 
  318.  
  319.     rts
  320.  
  321. ;
  322. ; INPUT a string from a RAW: window. a3 points to input string.
  323. ; Destructive backspace (ASCII 8) is handled as expected, while
  324. ; all other characters are passed into the final string.
  325. ;
  326. _inputrawstring:
  327.     move.l    a3,_rawinpaddr    ; save the address
  328.  
  329. _waitforinput:
  330.     move.l    _DOSBase,a6
  331.     move.l    _stdin,d1
  332.     moveq    #1,d2
  333.     jsr    _LVOWaitForChar(a6)
  334.     cmpi.w    #0,d0
  335.     beq.s    _waitforinput    
  336.  
  337.     ; get pending character
  338.     move.l    _DOSBase,a6
  339.     move.l    _stdin,d1
  340.     move.l    #_rawinpbuf,d2          ; address of buffer    
  341.     moveq    #1,d3            
  342.     jsr    _LVORead(a6)        ; read 1 character        
  343.  
  344.     ; is it a destructive backspace? 
  345.     cmpi.b    #8,_rawinpbuf
  346.     bne.s    _displayrawchar        ; no -> just display it    
  347.  
  348.     ; BS: are we back at the start of the line?
  349.     cmpa.l    _rawinpaddr,a3
  350.     beq.s    _waitforinput        ; yes -> can't delete any more!
  351.  
  352. _displayrawchar:
  353.     move.l    _DOSBase,a6
  354.     move.l    _stdout,d1
  355.     move.l    #_rawinpbuf,d2
  356.     moveq    #1,d3
  357.     jsr    _LVOWrite(a6)        ; display character
  358.  
  359.     ; is it a destructive backspace? 
  360.     cmpi.b    #8,_rawinpbuf
  361.     bne.s    _addchartostring    ; not BS, so keep it
  362.  
  363.     ; delete last character
  364.     suba.l    #1,a3            ; otherwise, move back one character
  365.  
  366.     move.l    _DOSBase,a6
  367.     move.l    _stdout,d1
  368.     move.b    #32,_rawinpbuf
  369.     move.l    #_rawinpbuf,d2
  370.     moveq    #1,d3
  371.     jsr    _LVOWrite(a6)        ; write a space over last character
  372.     
  373.     move.l    _DOSBase,a6
  374.     move.l    _stdout,d1
  375.     move.b    #8,_rawinpbuf        
  376.     move.l    #_rawinpbuf,d2
  377.     moveq    #1,d3
  378.     jsr    _LVOWrite(a6)        ; move back to "wiped-out" character
  379.  
  380.     bra    _waitforinput        ; then wait for next character
  381.  
  382. _addchartostring:
  383.     ; add to string
  384.     cmpi.b    #13,_rawinpbuf        ; carriage return? -> EOS
  385.     beq.s    _exitrawinput
  386.  
  387.     move.b    _rawinpbuf,(a3)+    ; add character to string
  388.  
  389.     bra    _waitforinput        ; wait for next character
  390.     
  391. _exitrawinput:
  392.     move.b    #0,(a3)
  393.     move.l    _rawinpaddr,a3        ; address of string
  394.  
  395.     move.l    #10,-(sp)
  396.     jsr    _putchar        ; Line Feed
  397.     addq    #4,sp
  398.  
  399.     rts
  400.  
  401. ;
  402. ; HEX$ - returns hexadecimal string form (a0) of short decimal value (d0).
  403. ;
  404. _hexstrshort:
  405.     move.l  a0,a3        ; save destination string address
  406.     move.w    d0,-(sp)    ; push short value
  407.     pea    _shorthexfmt    ; push format string
  408.     move.l    a0,-(sp)    ; push destination string
  409.     jsr    _sprintf
  410.     add.l    #10,sp
  411.     move.l    a3,a0        ; restore destination string address
  412.     rts
  413. ;
  414. ; HEX$ - returns hexadecimal string form (a0) of long decimal value (d0).
  415. ;
  416. _hexstrlong:
  417.     move.l  a0,a3        ; save destination string address
  418.     move.l    d0,-(sp)    ; push long value
  419.     pea    _longhexfmt    ; push format string
  420.     move.l    a0,-(sp)    ; push destination string
  421.     jsr    _sprintf
  422.     add.l    #12,sp
  423.     move.l    a3,a0        ; restore destination string address
  424.     rts
  425. ;
  426. ; OCT$ - returns octal string form (a0) of long decimal value (d0).
  427. ;
  428. _octstr:
  429.     move.l    a0,a3        ; save address of dest string
  430.  
  431.     ; if zero, make a string with 1 digit: "0"
  432.     cmpi.l    #0,d0
  433.     bne.s    _octnotzero
  434.     move.b    #48,(a0)+    ; string[0]='0'
  435.     move.b    #0,(a0)        ; EOS
  436.     movea.l    a3,a0
  437.     rts
  438.  
  439. _octnotzero:
  440.     move.w    #0,d2        ; cc=0
  441.     lea    _octdigit,a0
  442.  
  443. _octloop:
  444.     cmpi.l    #0,d0
  445.     beq.s    _reversedigits    ; until num == 0
  446.     
  447.     ; get remainder
  448.     move.l    d0,d1        ; num
  449.     move.l    d0,d3        
  450.     lsr.l    #3,d3        ; num\8
  451.     lsl.l    #3,d3        ; quotient*8
  452.     sub.l    d3,d1        ; r=num-(quotient*8) = num % 8
  453.         
  454.     add.l    #48,d1        ; ASCII = 48 + d1
  455.     and.b    #$ff,d1        
  456.     move.b    d1,(a0)+    ; x[cc]=r
  457.     addi.w    #1,d2        ; cc++ (keep count of characters)
  458.  
  459.     lsr.l    #3,d0        ; num \= 8
  460.     
  461.     bra.s    _octloop
  462.  
  463. _reversedigits:
  464.     move.l    a3,a1        ; string address
  465.  
  466. _makeoctstring:
  467.     cmpi.w    #0,d2
  468.     ble.s    _stripoctzeros    ; while cc > 0
  469.  
  470.     subi.w    #1,d2        ; --cc
  471.     move.b    -(a0),(a1)+    ; string[cc] = x[cc]
  472.  
  473.     bra.s    _makeoctstring
  474.  
  475. _stripoctzeros:
  476.     move.b    #0,(a1)        ; EOS
  477.     move.l    a3,a1        ; start of string 
  478.  
  479. _octstriploop:
  480.     ; strip leading zeros
  481.     cmpi.b    #0,(a1)
  482.     beq.s    _exitoctstr    ; exit if EOS (null string?)
  483.  
  484.     cmpi.b    #48,(a1)
  485.     bgt.s    _exitoctstr    ; digit > 0? -> exit    
  486.  
  487.     adda.l    #1,a1
  488.  
  489.     bra.s    _octstriploop
  490.         
  491. _exitoctstr:        
  492.     move.l    a1,a0        ; return destination string address
  493.     rts
  494.  
  495. ;
  496. ; STR$ - returns string form (a0) of short decimal value (d0). 
  497. ;
  498. _strshort:
  499.     move.l  a0,a3        ; save destination string address
  500.     cmpi.w  #0,d0        
  501.     blt.s    _strshortdo    ; is value >= 0? 
  502.     move.b    #32,(a0)+    ; yes -> leading space
  503. _strshortdo: 
  504.     move.w    d0,-(sp)    ; push short value
  505.     pea    _shortfmt    ; push format string
  506.     move.l    a0,-(sp)    ; push destination string
  507.     jsr    _sprintf
  508.     add.l    #10,sp
  509.     move.l    a3,a0        ; restore destination string address
  510.     rts
  511.  
  512. ;
  513. ; STR$ - returns string form (a0) of long decimal value (d0). 
  514. ;
  515. _strlong:
  516.     move.l  a0,a3        ; save destination string address
  517.     move.l  a0,a3        ; save destination string address
  518.     cmpi.l  #0,d0        
  519.     blt.s    _strlongdo    ; is value >= 0? 
  520.     move.b    #32,(a0)+    ; yes -> leading space
  521. _strlongdo: 
  522.     move.l    d0,-(sp)    ; push long value
  523.     pea    _longfmt    ; push format string
  524.     move.l    a0,-(sp)    ; push destination string
  525.     jsr    _sprintf
  526.     add.l    #12,sp
  527.     move.l    a3,a0        ; restore destination string address
  528.     rts
  529.  
  530. ;
  531. ; INKEY$ - returns a single character string (address in d0) from stdin if 
  532. ;       a character is pending or the NULL string if not. If IntuiMode
  533. ;       is 1, the Window's IDCMP port is checked for a VANILLAKEY event.
  534. ;
  535. _inkey:
  536.     cmpi.b    #0,_IntuiMode
  537.     beq    _stdinkey
  538.  
  539.     ; check for Intuition event
  540.     movea.l    _Wdw,a0
  541.     move.l    UserPort(a0),-(sp) ; get window's UserPort (Wdw->UserPort)
  542.     jsr    _GetIntuiEvent
  543.     addq    #4,sp
  544.  
  545.     tst.l    d0
  546.     bne.s    _checkforkey    ; an event took place!
  547.     bra.s    _quitintuiinkey ; no event took place
  548.  
  549. _checkforkey:
  550.     movea.l    d0,a0        ; pointer to IntuiInfo structure
  551.             
  552.     move.l    Class(a0),d1    ; Message->Class
  553.     andi.l    #VANILLAKEY,d1
  554.     cmpi.l    #VANILLAKEY,d1
  555.     beq.s    _getvanillakey
  556.  
  557.     ; no vanilla key event -> quit
  558.     bra.s    _quitintuiinkey 
  559.  
  560. _getvanillakey:
  561.     ; there's a vanilla key event
  562.     move.w    Code(a0),d1    ; Message->Code
  563.     andi.b    #$ff,d1
  564.  
  565.     ; construct string
  566.     movea.l    #_inkeybuf,a0
  567.     move.b    d1,(a0)+
  568.     move.b    #0,(a0)
  569.  
  570.     ; reply to message
  571.     jsr    _ClearIntuiEvent
  572.  
  573.     ; return address of string
  574.     move.l    #_inkeybuf,d0    
  575.     
  576.     rts
  577.     
  578. _quitintuiinkey:
  579.     ; no event or no vanilla key -> return NULL string
  580.     movea.l    #_inkeybuf,a0
  581.     move.b    #0,(a0)
  582.  
  583.     move.l    #_inkeybuf,d0    ; return address of string
  584.  
  585.     rts
  586.                         
  587. _stdinkey:    
  588.     move.l    _DOSBase,a6
  589.  
  590.     ; check for pending character(s)
  591.     move.l    _stdin,d1
  592.     moveq    #1,d2            ; wait 1 microsecond
  593.     jsr    _LVOWaitForChar(a6)
  594.     cmpi.w    #0,d0
  595.     bne.s    _readinkey
  596.  
  597.     move.l    #_inkeybuf,a0        
  598.     move.b    #0,(a0)            ; NULL string
  599.  
  600.     move.l    #_inkeybuf,d0        ; return address of string
  601.     
  602.     rts
  603.  
  604. _readinkey:
  605.     ; read one character
  606.     move.l    _stdin,d1
  607.     move.l    #_inkeybuf,d2
  608.     moveq    #1,d3
  609.     jsr    _LVORead(a6)
  610.         
  611.     move.l    #_inkeybuf,a0        
  612.     addq    #1,a0
  613.     move.b    #0,(a0)            ; EOS
  614.  
  615.     move.l    #_inkeybuf,d0        ; return address of string
  616.  
  617.     rts
  618.  
  619. ;
  620. ; SPACE$(n) - returns the address of a string (in d0) with n spaces. d0=n.
  621. ;        - destination string address in a0.
  622. ;
  623. _spacestring:
  624.     move.l    a0,_spacestraddress
  625.  
  626.     cmpi.w    #0,d0
  627.     ble.s    _quitspacestring    ; n <= 0 -> quit
  628.  
  629.     cmpi.w    #MAXSTRINGSIZE,d0
  630.     blt.s    _buildspacestring
  631.     move.w    #MAXSTRINGSIZE-1,d0    ; n >= MAXSTRINGSIZE -> clip
  632.  
  633. _buildspacestring:
  634.     move.b    #32,(a0)+
  635.     subq.w    #1,d0
  636.     cmpi.w    #0,d0
  637.     bgt.s    _buildspacestring
  638.         
  639. _quitspacestring:
  640.     move.b    #0,(a0)
  641.     move.l    _spacestraddress,d0
  642.  
  643.     rts
  644.  
  645. ;
  646. ; SPC(n) - returns the address of a string (in d0) with n spaces. d0=n.
  647. ;     - destination string address in a0.
  648. ;
  649. _spc:
  650.     move.l    a0,_spacestraddress
  651.  
  652.     cmpi.w    #0,d0
  653.     ble.s    _quitspcstring        ; n <= 0 -> quit
  654.  
  655.     cmpi.w    #255,d0
  656.     blt.s    _buildspcstring
  657.     move.w    #255,d0            ; n >= MAXSTRINGSIZE -> clip
  658.  
  659. _buildspcstring:
  660.     move.b    #32,(a0)+
  661.     subq.w    #1,d0
  662.     cmpi.w    #0,d0
  663.     bgt.s    _buildspcstring
  664.         
  665. _quitspcstring:
  666.     move.b    #0,(a0)
  667.     move.l    _spacestraddress,d0
  668.  
  669.     rts
  670.  
  671. ;
  672. ; STRING$(n,m) - returns the address of a string (in d0) with n characters
  673. ;         of ASCII value m. d0=n, d1=m.
  674. ;           - destination string address in a0.
  675. ;
  676. _stringstr:
  677.     move.l    a0,_stringstraddress
  678.  
  679.     cmpi.w    #0,d0
  680.     ble.s    _quitstringstr        ; n <= 0 -> quit
  681.  
  682.     cmpi.w    #MAXSTRINGSIZE,d0
  683.     blt.s    _buildstringstr
  684.     move.w    #MAXSTRINGSIZE-1,d0    ; n >= MAXSTRINGSIZE -> clip
  685.  
  686. _buildstringstr:
  687.     move.b    d1,(a0)+
  688.     subq.w    #1,d0
  689.     cmpi.w    #0,d0
  690.     bgt.s    _buildstringstr
  691.         
  692. _quitstringstr:
  693.     move.b    #0,(a0)
  694.     move.l    _stringstraddress,d0
  695.  
  696.     rts
  697.  
  698. ;
  699. ; INSTR([I,],X$,Y$) - returns the first occurrence of Y$ in X$.
  700. ;            - the search starts from MID$(X$,I,1).
  701. ;            - if I is not specified, it takes on a value of 1.
  702. ;            - the result is returned in d0. 
  703. ;            - d0=I, a0=X$, a1=Y$.
  704. ;
  705. _instr:
  706.     ; result in case of error
  707.     move.l    #0,_instrposn
  708.  
  709.     ; store the parameters
  710.     move.l    d0,_search_offset    ; I
  711.     move.l    a0,_x_string        ; X$
  712.     move.l    a1,_y_string        ; Y$
  713.     move.b    (a1),_targetch        ; first character of Y$
  714.  
  715.     ; is I < 1 ?
  716.     cmpi.l    #1,_search_offset
  717.     blt    _quitinstr        ; I <= 0 -> result=0
  718.  
  719.     ; find length of X$
  720.     movea.l    _x_string,a2
  721.     jsr    _strlen
  722.     move.l    d0,_x_strlen
  723.  
  724.     ; is X$="" ? 
  725.     cmpi.l    #0,d0
  726.     beq    _quitinstr        ; X$="" -> result=0
  727.  
  728.     ; is I > len(X$) ?
  729.     move.l    _search_offset,d1
  730.     cmp.l    d0,d1
  731.     bgt    _quitinstr        ; I > LEN(X$) -> result=0
  732.  
  733.     ; find length of Y$
  734.     movea.l    _y_string,a2
  735.     jsr    _strlen
  736.     move.l    d0,_y_strlen
  737.  
  738.     ; is len(Y$) > len(X$) ?
  739.     move.l    _x_strlen,d0
  740.     move.l    _y_strlen,d1
  741.     cmp.l    d0,d1
  742.     bgt    _quitinstr        ; len(Y$) > len(X$) -> result=0
  743.     
  744.     ; is Y$="" ?
  745.     cmpi.l    #0,_y_strlen
  746.     bne.s    _search_x_for_y        
  747.  
  748.     move.l    _search_offset,_instrposn
  749.     bra.s    _quitinstr        ; Y$="" -> result=I    
  750.  
  751. _search_x_for_y:
  752.           ; compare first character only
  753.     movea.l    _x_string,a0        ; A=address of first character in X$
  754.     adda.l    _search_offset,a0    ; A=A+I    
  755.     suba.l    #1,a0            ; A=A+I-1 (adjust to start at 0th byte)
  756.     move.b    (a0),d0
  757.     move.b    _targetch,d1        ; get first character from Y$
  758.     cmp.b    d0,d1
  759.     beq.s    _check_whole_string    ; first characters match
  760.     bra.s    _inc_search_offset    ; try next character
  761.  
  762. _check_whole_string:        
  763.     ; get MID$(X$,I,len(Y$))
  764.     movea.l    _x_string,a0    
  765.     lea    _tmpstring,a1
  766.     move.l    _search_offset,d0
  767.     move.l    _y_strlen,d1
  768.     jsr    _midstr            ; a0 = MID$(X$,I,len(Y$)) -> _streq
  769.  
  770.     ; is MID$(X$,I,len(Y$)) = Y$ ?
  771.     movea.l    _y_string,a1
  772.     jsr    _streq
  773.     cmpi.l    #0,d0
  774.     beq.s    _inc_search_offset    ; MID$(X$,I,len(Y$)) <> Y$ -> ++I
  775.     
  776.     ; found it!
  777.     move.l    _search_offset,_instrposn
  778.     bra.s    _quitinstr
  779.     
  780. _inc_search_offset:
  781.     add.l    #1,_search_offset
  782.     move.l    _x_strlen,d0
  783.     move.l    _search_offset,d1
  784.     cmp.l    d0,d1
  785.     ble.s    _search_x_for_y        
  786.         
  787. _quitinstr:
  788.     move.l    _instrposn,d0
  789.         
  790.     rts
  791.  
  792. ;
  793. ; BIN$ - returns binary string form (a0) of long decimal value (d0).
  794. ;
  795. _binstr:
  796.      move.l     a0,a3          ; save address of dest string
  797.  
  798.     ; if zero, make a string with 1 digit: "0"
  799.     cmpi.l     #0,d0
  800.     bne.s     _binnotzero
  801.     move.b     #48,(a0)+     ; string[0]='0'
  802.     move.b    #0,(a0)        ; EOS
  803.     movea.l    a3,a0
  804.     rts
  805.  
  806. _binnotzero:
  807.      move.w     #0,d2          ; cc=0
  808.      lea     _bindigit,a0
  809.  
  810. _binloop:
  811.      cmpi.l     #0,d0
  812.      beq.s     _revdigits     ; until num == 0
  813.  
  814.      ; get remainder
  815.      move.l     d0,d1          ; num
  816.      move.l     d0,d3  
  817.      lsr.l     #1,d3          ; num\2
  818.      lsl.l     #1,d3          ; quotient*2
  819.      sub.l     d3,d1          ; r=num-(quotient*2) = num % 2
  820.   
  821.      add.l     #48,d1         ; ASCII = 48 + d1
  822.      and.b     #$ff,d1  
  823.      move.b     d1,(a0)+     ; x[cc]=r
  824.      addi.w     #1,d2          ; cc++ (keep count of characters)
  825.  
  826.      lsr.l     #1,d0          ; num \= 2
  827.  
  828.      bra.s     _binloop
  829.  
  830. _revdigits:
  831.      move.l     a3,a1  ; string address
  832.  
  833. _makebinstring:
  834.      cmpi.w     #0,d2
  835.      ble.s     _stripbinzeros     ; while cc > 0
  836.  
  837.      subi.w     #1,d2  ; --cc
  838.      move.b     -(a0),(a1)+     ; string[cc] = x[cc]
  839.  
  840.      bra.s     _makebinstring
  841.     
  842. _stripbinzeros:
  843.      move.b     #0,(a1)      ; EOS
  844.      move.l     a3,a1          ; start of string 
  845.     
  846. _binstriploop:
  847.      ; strip leading zeros
  848.      cmpi.b     #0,(a1)
  849.      beq.s     _exitbinstr     ; exit if EOS (null string?)
  850.  
  851.      cmpi.b     #48,(a1)
  852.      bgt.s     _exitbinstr     ; digit > 0? -> exit 
  853.  
  854.      adda.l     #1,a1
  855.  
  856.      bra.s     _binstriploop
  857.   
  858. _exitbinstr:  
  859.      move.l     a1,a0          ; return destination string address
  860.     rts
  861.  
  862.     END
  863.